<template>
  <div>
  <NvLayout :nvsData="conditionNvsData" :is-root-layout="true" @define-event="handleEvent($event)"></NvLayout>
  <NvLayout :nvsData="resultNvsData" :is-root-layout="true" ref="filterResult" @define-event="handleEvent($event)"></NvLayout>
  <el-pagination class="el-paging"
                 @size-change="handlePageSizeChange"
                 @current-change="handleCurrentPageChange"
                 :current-page="page.currentPage"
                 :page-sizes="[10, 20, 30, 40, 50]"
                 :page-size="page.pagesize"
                 layout="total, sizes, prev, pager, next, jumper"
                 :total="page.total"
                 :background='true'
                 prev-text="上一页"
                 next-text="下一页">
  </el-pagination>
    <NvFilterDialog ref="nvFilterDialog"></NvFilterDialog>
  </div>
</template>

<script>
import NvLayout from '../../components/compound/NvLayout'
import { ref, onMounted, defineAsyncComponent } from 'vue'
import nvsDataUtils from '../../js/NvsDataUtils'
import NvsData from '../../js/NvsData'
import ConstDef from '../../js/ConstDef'
import nvFilterService from '../../api/NvFilterService'
import cacheManage from '../../cache/CacheManage'
import layoutUtils from '../../js/layout/LayoutUtils'
import { ElMessage } from 'element-plus'
import menuFunction from '../../js/MenuFunction'
import ndLayoutFilterExt from './ext/filterext/NdLayoutFilterExt'

export default {
  name: 'NvFilter',
  components: {
    NvLayout,
    NvFilterDialog: defineAsyncComponent(() => import('./NvFilterDialog.vue'))
  },
  props: {
    config: {
      type: Object,
      default: null
    }
  },
  setup(props) {
    const conditionNvsData = ref(null);
    const resultNvsData = ref(null);
    const page = ref({
      currentPage: 1,
      pageSize: 10,
      total: 0
    })

    function getFdAndAliasFromConditionFd(conditionFdName) {
      const filterFds = props.config.filterConditionFdNd;
      for (const filterFd of filterFds) {
        if (filterFd.fdAlias === conditionFdName) return filterFd;
      }
      for (const filterFd of filterFds) {
        if (filterFd.fdName === conditionFdName) return filterFd;
      }
      return null;
    }
    async function filterByDef(event) {
      const conditionNv = conditionNvsData.value.nvs[0];
      const conditionNd = conditionNvsData.value.nd;
      const filterFds = [];
      for (const fd of conditionNd.fds) {
        if (conditionNv[fd.fdName]) {
          const filterFdOfCondition = getFdAndAliasFromConditionFd(fd.fdName);
          if (filterFdOfCondition === null) continue;
          const filterFd = { ndName: filterFdOfCondition.ndName, fdName: filterFdOfCondition.fdName, fdAlias: filterFdOfCondition.fdAlias, value: conditionNv[fd.fdName], dataType: fd.dataType };
          filterFds.push(filterFd)
        }
      }

      const filterParam = {
        filterDefCode: props.config.code,
        filterFds,
        startNo: (page.value.currentPage - 1) * page.value.pageSize,
        count: page.value.pageSize
      };

      const commonInfo = cacheManage.getDefaultCommonInfo();
      const filterResultMsg = await nvFilterService.filterNvsByDef(commonInfo, filterParam);
      if (!filterResultMsg.success) { return; }
      const filterResult = filterResultMsg.value;
      page.value.total = filterResult.total;
      resultNvsData.value.nvs = filterResult.nvs;
    }
    onMounted(async () => {
      const conditionLayoutCode = props.config.conditionLayoutCode;
      const conditionNdCode = props.config.conditionNdCode;
      const resultNdCode = props.config.resultNdCode;
      const resultLayoutCode = props.config.resultLayoutCode;
      const conditionNvsDataMsg = await nvsDataUtils.initNvAndNdAndLayout(conditionNdCode, conditionLayoutCode);
      if (!conditionNvsDataMsg.success) { return; }
      conditionNvsData.value = new NvsData([conditionNvsDataMsg.nv], conditionNvsDataMsg.nd, conditionNvsDataMsg.layout);
      const resultNdAndLayoutMsg = await nvsDataUtils.getNdAndLayout(resultNdCode, resultLayoutCode);
      if (!resultNdAndLayoutMsg.success) { return; }
      resultNvsData.value = new NvsData([], resultNdAndLayoutMsg.nd, resultNdAndLayoutMsg.layout);
      if (props.config.action && props.config.action.autoFilter) {
        filterByDef();
        page.value.currentPage = 1;
      }
    })
    const filterExts = ref({
      ndLayoutFilterExt
    });
    function filterExtSupportEvent (functionCode) {
      if (props.config.extCode && filterExts.value[props.config.extCode]) {
        if (filterExts.value[props.config.extCode].supportEvent(functionCode)) { return true; }
      }
      return false;
    }

    function filterExtInterceptEvent (functionCode) {
      if (props.config.extCode && filterExts.value[props.config.extCode]) {
        if (filterExts.value[props.config.extCode].interceptEvent(functionCode)) { return true; }
      }
      return false;
    }

    function getFunctionConfig() {
      return {
        config: props.config,
        moduleCode: ConstDef.MODULE_CODE_FILTER
      }
    }

    return {
      conditionNvsData,
      resultNvsData,
      page,
      filterByDef,
      filterExts,
      filterExtSupportEvent,
      filterExtInterceptEvent,
      getFunctionConfig
    }
  },
  methods: {
    getSelectedNvs() {
      return this.$refs.filterResult.getSelectedNvs();
    },
    handleEvent(event) {
      const fvData = event.fvData;
      const functionCode = fvData.fdLayout.functionCode;
      if (this.filterExtInterceptEvent(functionCode)) {
        const filterExt = this.filterExts[this.config.extCode];
        filterExt.handleEvent(this, event);
      } else if (functionCode === ConstDef.FUNCTION_CODE_FILTER) {
        this.page.currentPage = 1;
        this.filterByDef(event);
      } else if (functionCode === ConstDef.FUNCTION_CODE_EDIT) {
        this.edit(event);
      } else if (functionCode === ConstDef.FUNCTION_CODE_COPY_NV) {
        this.copy(event)
      } else if (functionCode === ConstDef.FUNCTION_CODE_ADD_NV) {
        this.newNv(event);
      } else if (functionCode === ConstDef.FUNCTION_CODE_ADD_NV_CHOOSE_ND) {
        this.newNvForSelectNd(event);
      } else if (this.filterExtSupportEvent(functionCode)) {
        const filterExt = this.filterExts[this.config.extCode];
        filterExt.handleEvent(this, event);
      } else {
        this.$emit("define-event", event)
      }
    },

    handlePageSizeChange(val) {
      this.page.pageSize = val;
      this.filterByDef();
    },
    handleCurrentPageChange(val) {
      this.page.currentPage = val;
      this.filterByDef();
    },

    async queryLayoutCode(fvData) {
      const nv = fvData.getNv();
      const extension = await nvsDataUtils.getFdLayoutExtension(fvData.fdLayout, ConstDef.FD_LAYOUT_EXTENSION_QUERY_LAYOUT);
      let layoutCode = null;
      if (extension && extension.length > 0) {
        layoutCode = layoutUtils.getLayoutCodeByFdExtension(nv, extension[0]);
      }
      return layoutCode;
    },

    async getEntryTabPage(fvData) {
      const extensions = nvsDataUtils.getFdLayoutExtension(fvData.fdLayout, ConstDef.FD_LAYOUT_EXTENSION_ENTRY);
      if (extensions && extensions[0]) {
        const mdCode = extensions[0].mdCode;
        const mvCode = extensions[0].mvCode;
        const tabPageMsg = await menuFunction.getEntryConfigTabPage(mdCode, mvCode);
        return tabPageMsg;
      } else {
        return {
          success: true,
          value: null
        };
      }
    },
    hasEntryExtension(fvData) {
      const extensions = nvsDataUtils.getFdLayoutExtension(fvData.fdLayout, ConstDef.FD_LAYOUT_EXTENSION_ENTRY);
      if (extensions && extensions[0]) return true; else return false;
    },
    hasQueryLayoutExtension(fvData) {
      const extensions = nvsDataUtils.getFdLayoutExtension(fvData.fdLayout, ConstDef.FD_LAYOUT_EXTENSION_QUERY_LAYOUT);
      if (extensions && extensions[0]) return true; else return false;
    },
    async edit(event) {
      const fvData = event.fvData;
      const nv = fvData.getNv();
      const ndCode = nv.__actualNdCode;
      const id = nv.id;
      const layoutCode = await this.queryLayoutCode(fvData);
      if (this.hasEntryExtension(fvData)) {
        const tabPageMsg = await this.getEntryTabPage(fvData);
        if (!tabPageMsg.success) return;
        const tabPage = tabPageMsg.value;
        tabPage.config.nvId = id;
        tabPage.config.ndCode = ndCode;
        if (layoutCode) tabPage.config.layoutCode = layoutCode;
        tabPage.config.action = 'query';
        this.$emit("tabPage", tabPage);
      } else {
        const tabPage = {
          name: this.config.name + "edit",
          title: this.config.description + "编辑",
          moduleCode: ConstDef.MODULE_CODE_ENTRY,
          config: {
            nvId: id,
            ndCode,
            layoutCode: layoutCode || this.config.detailLayoutCode,
            action: 'query'
          }
        };
        this.$emit("tabPage", tabPage);
      }
    },
    async copy(event) {
      const fvData = event.fvData;
      const nv = fvData.getNv();
      const ndCode = nv.__actualNdCode;
      const id = nv.id;
      const layoutCode = await this.queryLayoutCode(fvData);
      if (this.hasEntryExtension(fvData)) {
        const tabPageMsg = await this.getEntryTabPage(fvData);
        if (!tabPageMsg.success) { return; }
        const tabPage = tabPageMsg.value;
        tabPage.config.nvId = id;
        tabPage.config.ndCode = ndCode;
        if (layoutCode) tabPage.config.layoutCode = layoutCode;
        tabPage.config.action = 'copy';
        this.$emit("tabPage", tabPage);
      } else {
        const tabPage = {
          name: this.config.name + "copy",
          title: this.config.description + "复制",
          moduleCode: ConstDef.MODULE_CODE_ENTRY,
          config: {
            nvId: id,
            ndCode,
            layoutCode: layoutCode || this.config.detailLayoutCode,
            action: 'copy'
          }
        };
        this.$emit("tabPage", tabPage);
      }
    },
    async newNv(event) {
      const fvData = event.fvData;
      const ndCode = this.config.returnNdCode;
      const layoutCode = await this.queryLayoutCode(fvData);
      if (this.hasEntryExtension(fvData)) {
        const tabPageMsg = await this.getEntryTabPage(fvData);
        if (!tabPageMsg.success) return;
        const tabPage = tabPageMsg.value;
        tabPage.config.nvId = 0;
        if (layoutCode) tabPage.config.layoutCode = layoutCode;
        tabPage.config.action = 'init';
        this.$emit("tabPage", tabPage);
      } else {
        const tabPage = {
          name: this.config.name + "new",
          title: this.config.description + "新建",
          moduleCode: ConstDef.MODULE_CODE_ENTRY,
          config: {
            nvId: 0,
            ndCode,
            layoutCode: layoutCode || this.config.detailLayoutCode,
            action: 'init'
          }
        };
        this.$emit("tabPage", tabPage);
      }
    },
    async newNvForSelectNd(event) {
      const fvData = event.fvData;
      const fdLayout = fvData.fdLayout;
      const str = fdLayout.expression;
      if (!str) {
        ElMessage({
          type: 'error',
          message: '创建实例按钮没有配置表达式！',
          showClose: true
        })
      }
      const expression = JSON.parse(str);
      const filterDefCode = expression.filterDefCode;
      if (!filterDefCode) {
        ElMessage({
          type: 'error',
          message: `没没有配置查询定义代码，请确认按钮表达式中是否正确配置了filterDefCode`,
          showClose: true
        });
        return;
      }
      const filterConfigMsg = await menuFunction.getFilterConfig(ConstDef.FILTER_FUNCTION, filterDefCode);
      if (!filterConfigMsg.success) return;
      const filterConfig = filterConfigMsg.value;
      filterConfig.action.autoFilter = true;
      this.$refs.nvFilterDialog.showSingleChoose(filterConfig, async (nv) => {
        const ndCode = nv[expression.ndCodeKey];
        if (!ndCode) {
          ElMessage({
            type: 'error',
            message: `没有返回即将创建的nd代码，请确认按钮表达式中是否正确配置了ndCodeKey`,
            showClose: true
          });
          return;
        }
        const layoutCode = await layoutUtils.getLayoutCodeByKey(ndCode);
        if (!layoutCode) {
          ElMessage({
            type: 'error',
            message: `nd代码为${ndCode}没有配置关联的页面代码！`,
            showClose: true
          });
          return;
        }
        const tabPage = {
          name: this.config.name + "new",
          title: this.config.description + "新建",
          moduleCode: ConstDef.MODULE_CODE_ENTRY,
          config: {
            nvId: 0,
            ndCode,
            layoutCode: layoutCode,
            action: 'init'
          }
        };
        this.$emit("tabPage", tabPage);
      });
    }
  }
}
</script>

<style scoped>
</style>
